/*******************************************************************************
 * This file is part of Crunch Network.
 *
 * Crunch Network is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * Crunch Network is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * Crunch Network.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

package com.crunch.network.stateelements;

import com.crunch.network.StateElement;
import com.crunch.network.util.BitStreamReader;
import com.crunch.network.util.BitStreamWriter;

import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;

/**
 * A {@link com.crunch.network.StateElement} containing an integer.
 */
public class IntElement extends StateElement {
	/**
	 * Constructs the element.
	 *
	 * @param   networkTransmissionMode the mode of network transmission to use for this element.
	 * @param   bitCount the number of bits to use.
	 */
	public IntElement(NetworkTransmissionMode networkTransmissionMode, int bitCount) {
		super(networkTransmissionMode);

		if (bitCount <= 0 || bitCount > 32) {
			throw new IllegalArgumentException("Invalid bit count");
		}

		this.value = 0;
		this.bitCount = bitCount;
	}

	/**
	 * Assigns a new value, dirtying the element if the value has changed.
	 *
	 * @param   value the new value.
	 */
	public void setValue(int value) {
		int truncatedValue = value & ~(0xffffffff << bitCount);
		if (truncatedValue != this.value) {
			this.value = truncatedValue;
			setDirty();
		}
	}

	/**
	 * Returns the element's value.
	 *
	 * @return  the element's value.
	 */
	public int getValue() {
		return value;
	}

	/**
	 * Reads the element from the stream.
	 *
	 * @param   reader the stream from which element data should be read.
	 * @throws  BufferUnderflowException if too little data is available for reading.
	 * @throws  IOException if an error in the data is detected.
	 */
	@Override
	public void read(BitStreamReader reader)
			throws BufferUnderflowException, IOException {
		value = reader.readInt(bitCount);
	}

	/**
	 * Writes the element to the stream.
	 *
	 * @param   writer the stream to which element data should be written.
	 * @throws  BufferOverflowException if too much data is available for writing.
	 */
	@Override
	public void write(BitStreamWriter writer)
			throws BufferOverflowException {
		writer.writeInt(value, bitCount);
	}

	private int value;
	private int bitCount;
}
